﻿using System.Threading.Tasks;
using P4 = Red.Core.Perforce;

namespace Red.Launcher.Utilities
{
    public static class P4MediatorExtension
    {
        private static async Task<string> Prompt( P4.Mediator mediator, string username )
        {
            Dialogs.UserSignin dialog = new Dialogs.UserSignin()
            {
                Owner = App.Current.MainWindow,
                IsUsernameReadOnly = true,
                Username = username,
                ShowDomain = false,
                Title = "Please enter password for specified Perforce account"
            };

            if( await dialog.ShowAsync() )
            {
                return dialog.Password;
            }

            return null;
        }

        private enum SigninState
        {
            NotInitialized,
            SignedIn,
            SignedOut,
            Error
        }

        private static SigninState SigninInternal( P4.Mediator mediator, string password )
        {
            SigninState state = SigninState.NotInitialized;

            P4.Mediator.ErrorEventHandler errorHandler = ( string message ) => state = SigninState.Error;
            P4.Mediator.NotSignedInEventHandler signinHandler = ( string username ) => state = SigninState.SignedOut;

            mediator.Error += errorHandler;
            mediator.NotSignedIn += signinHandler;

            if ( mediator.SignIn( password ) )
            {
                state = SigninState.SignedIn;
            }

            mediator.Error -= errorHandler;
            mediator.NotSignedIn -= signinHandler;

            return state;
        }

        private static async Task<SigninState> Signin( P4.Mediator mediator, string password )
        {
            TaskCompletionSource<SigninState> state = new TaskCompletionSource<SigninState>();

            Core.SourceControl.Monitor monitor = new Core.SourceControl.Monitor() { SourceControl = mediator };

            await Task.Run( () => state.SetResult( SigninInternal( mediator, password ) ) );
            
            monitor.Clear();
            monitor.SourceControl = null;

            return state.Task.Result;
        }

        private static async Task<SigninState> IsSignedIn( P4.Mediator mediator )
        {
            return await Signin( mediator, null );
        }

        public static async Task<bool> SignInCheckAndPrompt( this P4.Mediator mediator )
        {
            if ( !mediator.IsInitialized )
            {
                return false;
            }

            SigninState state = await IsSignedIn( mediator );

            while ( state == SigninState.SignedOut )
            {
                string password = await Prompt( mediator, mediator.Username );
                if ( password == null ) break;

                state = await Signin( mediator, password );
            }

            return state == SigninState.SignedIn;
        }
    }
}
